﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
using System.Net;
using System.Xml;
using System.IO;
using System.Collections.ObjectModel;

namespace Roweb
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.Title = String.Format(this.Title, Assembly.GetExecutingAssembly().GetName().Version.ToString());

            StructList.Items.Clear();
            ((GridView)StructList.View).Columns.Clear();
            StructList.ItemsSource = StructListItems;
        }

        private ObservableCollection<Dictionary<string, string>> StructListItems = new ObservableCollection<Dictionary<string, string>>();
        //private static int StructListItemsAttrId = 0;

        private void GotoUriButton_Click(object sender, RoutedEventArgs e)
        {
            //WebClient webClient = new WebClient();
            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(DownloadUriContent), new DownloadUriContentArgs() { Uri = new Uri(UriBox.Text) });
            //using (WebClient webClient = new WebClient())
            {
                //string content = webClient.DownloadString(new Uri(UriBox.Text));
                //ContentBox.Text = content;
            }

            ContentBox.Text = null;
            StructTree.Items.Clear();
            InitGradientStops();

            //System.Threading.Timer timer = new System.Threading.Timer(new System.Threading.TimerCallback(QueryTimeoutUpdate), null, TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0));
            System.Threading.Timer timer = new System.Threading.Timer(new System.Threading.TimerCallback(QueryTimeoutUpdate));
            timer.Change(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0));
        }

        private void InitGradientStops()
        {
            LinearGradientBrush brushBack = (LinearGradientBrush)UriBox.Background;
            brushBack.GradientStops[0].Offset = 0.0;
            brushBack.GradientStops[1].Offset = 0.05;
        }

        private void QueryTimeoutUpdate(object state)
        {
            System.Threading.Timer timer = (System.Threading.Timer)state;

            this.Dispatcher.Invoke(new Action(delegate()
            {
                LinearGradientBrush brushBack = (LinearGradientBrush)UriBox.Background;
                brushBack.GradientStops[0].Offset += 0.1;
                brushBack.GradientStops[1].Offset += 0.1;

                if (brushBack.GradientStops[1].Offset >= 1.0)
                {
                    timer.Dispose();
                    InitGradientStops();
                }

                UriBox.InvalidateVisual();
            }));
        }

        class DownloadUriContentArgs
        {
            public Uri Uri;
        }

        private void DownloadUriContent(object state)
        {
            //var s = state;
            using (WebClient webClient = new WebClient())
            {
                string content = webClient.DownloadString(((DownloadUriContentArgs)state).Uri);//s.Uri);//new Uri(UriBox.Text));
                //ContentBox.Text = content;
                this.Dispatcher.Invoke(new Action(delegate()
                {
                    ContentBox.Text = content;
                    ParseContentToStruct();
                }));
            }
        }

        private void ParseContentToStruct()
        {
            StructTree.Items.Clear();
            //StructList.Items.Clear();
            //((GridView)StructList.View).Columns.Clear();
            StructListItems.Clear();
            //bool col = ((GridView)StructList.View).Columns.Any((item) => (item.Header.ToString() == "name"));

            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ParseUriContent), null);// new DownloadUriContentArgs() { Uri = new Uri(UriBox.Text) });
        }

        private void ParseUriContent(object state)
        {
            string content = "";
            this.Dispatcher.Invoke(new Action(delegate(){
                content = ContentBox.Text;
            }));

            XmlDocument xmlDoc = new XmlDocument();

            using (StringReader stringReader = new StringReader(content))
            using (Sgml.SgmlReader sgmlReader = new Sgml.SgmlReader())
            {
                sgmlReader.DocType = "HTML";
                sgmlReader.WhitespaceHandling = WhitespaceHandling.None;//.All;
                sgmlReader.CaseFolding = Sgml.CaseFolding.ToLower;
                sgmlReader.InputStream = stringReader;

                //xmlDoc.LoadXml(content);
                xmlDoc.PreserveWhitespace = true;
                xmlDoc.XmlResolver = null;
                xmlDoc.Load(sgmlReader);

                StringBuilder xmlVersion = new StringBuilder();
                using (StringWriter strWriter = new StringWriter(xmlVersion))
                using(XmlTextWriter xmlWriter = new XmlTextWriter(strWriter))
                {
                    xmlWriter.Indentation = 4;
                    xmlWriter.Formatting = Formatting.Indented;
                    xmlDoc.Save(xmlWriter);
                    //xmlDoc.Save("webpage.xml");
                }
                this.Dispatcher.Invoke(new Action(delegate()
                {
                    ContentBox.Text = xmlVersion.ToString();
                }));
            }

            ParseContentNode(xmlDoc.DocumentElement, null, null);

            StructTree.Dispatcher.Invoke(new Action(delegate()
                {
                    //StructTree.
                }));
        }

        private void ParseContentNode(XmlNode xmlElement, XmlNode xmlParent, TreeViewItem treeParent)
        {
            TreeViewItem treeItem = null;// = new TreeViewItem();

            StructTree.Dispatcher.Invoke(new Action(delegate()
            {
                treeItem = new TreeViewItem();
                treeItem.Header = xmlElement.Name;

                Dictionary<string,string> attrDic = new Dictionary<string, string>();

                if (xmlElement.Attributes != null)
                {
                    foreach (XmlAttribute attr in xmlElement.Attributes)
                    {
                        //int attrId = StructListItemsAttrId++;
                        GridViewColumn col = ((GridView)StructList.View).Columns.FirstOrDefault((item) => (item.Header.ToString() == attr.Name));
                        //bool col = ((GridView)StructList.View).Columns..Any((item) => (item.Header.ToString() == attr.Name));
                        if (col == null)//default(GridViewColumn))
                        //if (!col)
                        {
                            //col = 
                            ((GridView)StructList.View).Columns.Add(new GridViewColumn() { Header = attr.Name, Width = 50.0, DisplayMemberBinding = new Binding("[" + attr.Name + "]"), });
                            //((GridView)StructList.View).Columns.Add(new GridViewColumn() { Header = attr.Name, Width = 50.0, DisplayMemberBinding = new Binding(attr.Name), });
                        }

                        attrDic.Add(attr.Name, attr.Value);
                        //ListViewItem listItem = new ListViewItem();
                        //List<string> content = new List<string>();
                        //content.Add(attr.Value);
                        //listItem.Content = content;// attr.Value;
                        //StructList.Items.Add(listItem);
                    }
                }

                StructListItems.Add(attrDic);

                if (treeParent == null)
                {
                    StructTree.Items.Add(treeItem);
                }
                else
                {
                    treeParent.Items.Add(treeItem);
                }
            }));

            foreach (XmlNode child in xmlElement.ChildNodes)
            {
                ParseContentNode(child, xmlElement, treeItem);
            }
        }

        //private void ReceivingNewContent(string content)
        //{
        //}
    }
}
